#lang racket
;Projet SomeWeirdDream
;Par l'équipe des semi-croustillants
;v0.0.0
(require rsound)
(require rsound/piano-tones)
(require 2htdp/image 2htdp/universe)
(host-api 'paASIO) 
;================ 1 - Structures globales ================
(define-struct note (son type) #:mutable #:transparent)
(define-struct monde (temps-attente partition) #:mutable #:transparent)
(define-struct balle (rayon couleur) #:mutable #:transparent)


;================ 2 - Variable globales ================
(define ticks-par-seconde 48) ;En une seconde, l'animation principale tickera combien de fois ?


;================ 2 - Fonctions prestataires de services ================

;get-temps-attente
;Prend une note et retourne, en fonction de son type (noire, blanche...)
;le nombre de cycles qu'il faudra attendre avant de jouer la note suivante
(define (get-temps-attente n)
  (define type (note-type n))
  (cond[(equal? type "noire") ticks-par-seconde]
       [(equal? type "blanche") (* 2 ticks-par-seconde)]
       [else (error "Type de note inconnu")]))
       
;changer-couleur
;change la couleur 
(define (changer-couleur b)
  (set-balle-couleur! b (make-color (random 256) (random 255) (random 255))))

;================ 3 - Définition de l'animation principale ================
(define (some-weird-dream _partition) 
  (define temps-attente ticks-par-seconde) ;On commence par un silence pour plus de propreté
  (define INIT (make-monde temps-attente _partition))
  (define BG (rectangle 300 300 'solid 'yellow))
  (define ma-balle (make-balle 50 "red"))
  (define ps (make-pstream))
  
  (define (suivant m)
    (define temps-restant (monde-temps-attente m))
    (define partition (monde-partition m))
    (if (= temps-restant 0)
        (begin (pstream-play ps (note-son (car partition)))                         ;Si le nous n'avons plus à attendre, alors on joue la note
               (set-monde-temps-attente! m (get-temps-attente (car partition)))     ;puis on reset le temps d'attente en fonction du type de note
               (changer-couleur ma-balle)                                           ;puis on change la couleur de la balle
               (set-monde-partition! m (cdr partition))                             ;puis on enlève la note jouée de la partition
               m)                                                                   ;enfin on retourne le monde
        
        (begin (set-monde-temps-attente! m (- temps-restant 1))   ;Si nous devons attendre, nous décrémentons le temps attendu de 1
               m)))
  
  (define (dessiner m)
    (overlay (circle (balle-rayon ma-balle) 'solid (balle-couleur ma-balle)) ;on créer un cercle à partir de notre structure balle 
             BG))
  
  (define (finished? m) ;L'animation s'arrête lorsque la partition est finie
    (empty? (monde-partition m)))
  
  (big-bang INIT
            (on-tick suivant (/ 1 ticks-par-seconde))
            (on-draw dessiner)
            (stop-when finished?)))


;================ 4 - Tests et notes ================
(define do-piano (piano-tone 60))
;(define ma-note (make-note 'son 'noire))
;> ma-note
;(note 'son 'noire)
;> (set-note-son! ma-note 'son2)
;> ma-note
;(note 'son2 'noire)

;J'ai envie de mettre un objet à la place de la note qui aurait comme attribut "muet" 
;sa durée en nombre de cycles. Peut on se débrouiller avec une structure sans que
;ça soit trop moche ?
(define ma-note (make-note do-piano "noire"))
(define ma-blanche (make-note do-piano "blanche"))
(define ma-partition (list ma-note ma-note ma-note ma-blanche ma-note))
;> ma-partition
;(list (note (rsound #<s16vector> 0 132300 44100) "noire") (note (rsound #<s16vector> 0 132300 44100) "noire") (note (rsound #<s16vector> 0 132300 44100) "noire"))
;> (some-weird-dream ma-partition)
;(monde 0 (list (note (rsound #<s16vector> 0 132300 44100) "noire") (note (rsound #<s16vector> 0 132300 44100) "noire") (note (rsound #<s16vector> 0 132300 44100) "noire")))
(some-weird-dream ma-partition)



;================ 5 - TODOS ================